/* 
	* Created by : Varun Tyagi
	* 
	* This program demonstrates how to detect key presses.
*/

/* Include the header files. */
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_ttf.h"
#include <string>

/* Global screen attributes. */
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

/* Window surfaces. */
SDL_Surface *pBackground = nullptr;
SDL_Surface *pUpMessage = nullptr;
SDL_Surface *pDownMessage = nullptr;
SDL_Surface *pLeftMessage = nullptr;
SDL_Surface *pRightMessage = nullptr;
SDL_Surface *pMessage = nullptr;
SDL_Surface *pScreen = nullptr;

/* The event structure. */
SDL_Event event;

/* TTF_Font. */
TTF_Font *pFont = nullptr;

/* Color of the font. */
SDL_Color textColor = { 1, 0, 0 };

/* Image loader. */
SDL_Surface *load_image( std::string filename )
{
	/* The default loaded image. */
	SDL_Surface *pLoadedImage = nullptr;

	/* The optimized version of the loaded image. */
	SDL_Surface *pOptimizedImage = nullptr;

	/* Load the image. */
	pLoadedImage = IMG_Load( filename.c_str() );

	/* Check to see if the file has been loaded properly. */
	if( nullptr != pLoadedImage )
	{
		/* Create an optimized version of the image. */
		pOptimizedImage = SDL_DisplayFormat( pLoadedImage );

		/* Free the old surface. */
		SDL_FreeSurface( pLoadedImage );

		/* Check to see if the file has been optimized or not. */
		if( nullptr != pOptimizedImage )
		{
			/* Color key surface. */
			SDL_SetColorKey( pOptimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( pOptimizedImage->format, 0, 0xFF, 0xFF ) );
		}
	}

	/* Return the optimized image. */
	return pOptimizedImage;
}

/* Apply the image. */
void apply_surface( int x, int y, SDL_Surface *pSource, SDL_Surface *pDestination, SDL_Rect *pClip = nullptr )
{
	/* Holds the offset. */
	SDL_Rect offset;

	offset.x = x;
	offset.y = y;
	
	/* Blit the image. */
	SDL_BlitSurface( pSource, pClip, pDestination, &offset );
}

/* Init SDL. */
bool init_SDL( void )
{
	/* Initialize all the subsystems. */
	if( -1 == SDL_Init( SDL_INIT_EVERYTHING ) )
	{
		/* Quit. */
		return false;
	}

	/* Set up the screen. */
	pScreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

	/* Check to see if we have correctly set up the screen. */
	if( nullptr == pScreen )
	{
		/* QUIT. */
		return false;
	}

	/* Initialize SDL_ttf. */
	if( -1 == TTF_Init() )
	{
		/* We couldn't initialize font, QUIT. */
		return false;
	}

	/* Set the window caption. */
	SDL_WM_SetCaption( "Checking KeyPresses", nullptr );

	/* If everything went as expected, return true. */
	return true;
}

/* File loader. */
bool load_file( void )
{
	/* Load the background image. */
	pBackground = load_image( "background.png" );

	/* Check to see if the background is loaded properly. */
	if( nullptr == pBackground )
	{
		return false;
	}

	/* Open the font. */
	pFont = TTF_OpenFont( "SketchFlow Print.ttf", 50 );

	/* Check to see if the font is loaded properly. */
	if( nullptr == pFont )
	{
		return false;
	}

	/* Return true if everything has been loaded properly. */
	return true;
}

/* Clean up. */
void clean_SDL( void )
{
	/* Free all the surfaces. */
	SDL_FreeSurface( pBackground );
	SDL_FreeSurface( pMessage );
	SDL_FreeSurface( pRightMessage );
	SDL_FreeSurface( pLeftMessage );
	SDL_FreeSurface( pUpMessage );
	SDL_FreeSurface( pDownMessage );

	/* Close the font. */
	TTF_CloseFont( pFont );

	/* QUIT SDL_ttf. */
	TTF_Quit();

	/* QUIT SDL. */
	SDL_Quit();
}

/* Main Function. */
int main( int argc, char** argv )
{
	/* QUIT flag. */
	bool bQuit = false;

	/* Initialize. */
	if( false == init_SDL() )
	{
		/* QUIT. */
		return 1;
	}

	/* Load all the needed files. */
	if( false == load_file() )
	{
		return false;
	}

	/* Generate the message surfaces. */
	pUpMessage = TTF_RenderText_Solid( pFont, "Up was pressed.", textColor );
	pDownMessage = TTF_RenderText_Solid( pFont, "Down was pressed.", textColor );
	pLeftMessage = TTF_RenderText_Solid( pFont, "Left was pressed.", textColor );
	pRightMessage = TTF_RenderText_Solid( pFont, "Right was pressed.", textColor );

	/* Apply the background. */
	apply_surface( 0, 0, pBackground, pScreen );

	/* While the user has not quit. */
	while( false == bQuit )
	{
		/* If there is an event to handle. */
		if( SDL_PollEvent( &event ) )
		{
			/* Check for key presses. */
			if( SDL_KEYDOWN == event.type )
			{
				/* Set the proper message surface. */
				switch( event.key.keysym.sym )
				{
				case SDLK_UP:
				case SDLK_KP8:
					{
						pMessage = pUpMessage;
						break;
					}
				case SDLK_DOWN:
				case SDLK_KP2:
					{
						pMessage = pDownMessage;
						break;
					}
				case SDLK_LEFT:
				case SDLK_KP4:
					{
						pMessage = pLeftMessage;
						break;
					}
				case SDLK_RIGHT:
				case SDLK_KP6:
					{
						pMessage = pRightMessage;
						break;
					}
				}
			}

			/* Else if the user has pressed QUIT. */
			else if( SDL_QUIT == event.type )
			{
				/* Quit the program. */
				bQuit = true;
			}
		}

		/* If a message needs to be displayed. */
		if( nullptr != pMessage )
		{
			/* Apply the background to the screen. */
			apply_surface( 0, 0, pBackground, pScreen );

			/* Apply the message centered on the screen. */
			apply_surface( ( SCREEN_WIDTH - pMessage->w ) / 2, ( SCREEN_HEIGHT - pMessage->h ) / 2, pMessage, pScreen );

			/* Null the surface pointer. */
			pMessage = NULL;
		}

		/* Update the screen. */
		if( SDL_Flip( pScreen ) == -1 )
		{
			return 1;
		}
	}

	/* Clean up SDL */
	clean_SDL();

	/* Return. */
	return 0;
}
